package cn.virens.common.spring.retry.annotations.config;

import cn.hutool.core.map.MapUtil;
import cn.virens.common.spring.retry.annotations.handler.VirRetryAnnotationSource;
import cn.virens.common.spring.retry.annotations.handler.VirRetryMethodInterceptor;
import cn.virens.common.spring.retry.annotations.handler.VirRetryMethodPointcutAdvisor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.annotation.Role;
import org.springframework.core.Ordered;
import org.springframework.core.type.AnnotationMetadata;

import java.util.Map;

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class VirRetryConfiguration implements ImportAware {
    protected int order = Ordered.LOWEST_PRECEDENCE;

    @Bean("virRetryAnnotationSource")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirRetryAnnotationSource virRetryAnnotationSource() throws Exception {
        return new VirRetryAnnotationSource();
    }

    @Bean("virRetryMethodInterceptor")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirRetryMethodInterceptor virRetryMethodInterceptor() throws Exception {
        return new VirRetryMethodInterceptor(virRetryAnnotationSource());
    }

    @Bean("virRetryMethodPointcutAdvisor")
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public VirRetryMethodPointcutAdvisor virRetryMethodPointcutAdvisor() throws Exception {
        VirRetryMethodPointcutAdvisor advisor = new VirRetryMethodPointcutAdvisor();
        advisor.setAnnotationSource(virRetryAnnotationSource());
        advisor.setAdvice(virRetryMethodInterceptor());
        advisor.setOrder(order);

        return advisor;
    }

    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        Map<String, Object> attributes = getAnnotationAttributes(importMetadata);

        this.order = MapUtil.getInt(attributes, "order", Ordered.LOWEST_PRECEDENCE);
    }

    protected Map<String, Object> getAnnotationAttributes(AnnotationMetadata importMetadata) {
        return importMetadata.getAnnotationAttributes(EnableVirRetry.class.getName(), false);
    }
}
